package com.sjs.flow.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sjs.flow.entity.FlowProcess;
import com.sjs.flow.entity.vo.ExcuteProcessVo;
import com.sjs.flow.entity.vo.ProcessDefinitionVo;
import com.sjs.flow.http.exception.PlatformException;
import com.sjs.flow.mapper.FlowProcessMapper;
import com.sjs.flow.protocol.PlatformErrorCode;
import com.sjs.flow.service.BpmnModelService;
import com.sjs.flow.service.FlowProcessService;
import com.sjs.flow.utils.FlowIdUtil;
import liquibase.pro.packaged.A;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * @author uto_dev_008
 * @desc
 * @since 2022/7/26 17:54
 * Copyright (c) 2021 南京友拓信息技术有限公司 All rights reserved
 */
@Service
public class FlowProcessServiceImpl extends ServiceImpl<FlowProcessMapper, FlowProcess> implements FlowProcessService {
    private Logger logger = LoggerFactory.getLogger(FlowProcessServiceImpl.class);
    @Autowired
    BpmnModelService bpmnModelService;

    @Resource
    FlowProcessMapper flowProcessMapper;

    @Autowired
    RuntimeService runtimeService;

    /**
     * 新增流程
     *
     * @param f
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(FlowProcess f) {
//        Integer type = f.getProcessType();
//        if (1 == type) {
//        } else {
//            throw new PlatformException("暂未支持的类型", PlatformErrorCode.SYS_ERROR.getCode());
//        }
        ProcessDefinitionVo processDefinitionVo = new ProcessDefinitionVo(f.getProcessKey(), f.getBpmnXml());
        Deployment deployment;
        try {
            deployment = bpmnModelService.generateProcess(processDefinitionVo);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new PlatformException("流程定义保存失败，流程配置不正确", PlatformErrorCode.SYS_ERROR.getCode());
        }
        f.setId(FlowIdUtil.getSnowId());
        f.setProcessId(deployment.getId());
        flowProcessMapper.insert(f);
        QueryWrapper<FlowProcess> processWrapper = new QueryWrapper<>();
        processWrapper.lambda().eq(FlowProcess::getProcessKey, f.getProcessKey()).
                eq(FlowProcess::getProcessStatus, 0);
        int count = flowProcessMapper.selectCount(processWrapper);
        if (count > 1) {
            throw new PlatformException("流程已存在", PlatformErrorCode.SYS_ERROR.getCode());
        }
    }

    /**
     * 执行流程
     *
     * @param vo
     */
    @Override
    public String excuteProcess(ExcuteProcessVo vo) {
        String processKey = vo.getProcessKey();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey, vo.getVars());
        return processInstance.getId();
    }

    /**
     * 获取所有流程
     *
     * @param processKey
     * @return
     */
    @Override
    @Transactional
    public List<FlowProcess> getFlowProcess(String processKey) {
        QueryWrapper<FlowProcess> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(processKey)) {
            wrapper.lambda().eq(FlowProcess::getProcessKey, processKey);
        }
        wrapper.lambda().orderByDesc(FlowProcess::getUpdateTime);
        List<FlowProcess> processList = this.list(wrapper);
        if (!CollectionUtils.isEmpty(processList)) {
            processList.forEach(process -> {
                try {
                    String bpmnXml = bpmnModelService.getDefinition(process.getProcessKey());
                    process.setBpmnXml(bpmnXml);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    throw new PlatformException(e.getMessage(),PlatformErrorCode.SYS_ERROR.getCode());
                }
            });
        }
        return processList;
    }


}
